package com.codeplatform.controller;

import com.codeplatform.service.WebSocketService;
import io.swagger.annotations.Api;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.handler.annotation.DestinationVariable;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.handler.annotation.SendTo;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.stereotype.Controller;

import java.security.Principal;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * WebSocket控制器
 * 处理客户端连接和实时消息传递
 * 
 * @author CodePlatform
 * @since 2024-01-01
 */
@Api(tags = "WebSocket控制管理")
@Slf4j
@Controller
public class WebSocketController {

    @Autowired
    private WebSocketService webSocketService;

    // 在线用户统计
    private final AtomicInteger onlineCount = new AtomicInteger(0);
    private final AtomicInteger executingCount = new AtomicInteger(0);
    
    // 会话管理
    private final Map<String, String> sessionUsers = new ConcurrentHashMap<>();
    private final Map<String, Long> userSessions = new ConcurrentHashMap<>();

    /**
     * 处理客户端订阅执行频道
     */
    @SubscribeMapping("/topic/execution/{sessionId}")
    public Map<String, Object> subscribeExecution(@DestinationVariable String sessionId, Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "anonymous";
            log.info("用户 {} 订阅执行频道: {}", username, sessionId);
            
            // 记录会话
            sessionUsers.put(sessionId, username);
            if (principal != null) {
                userSessions.put(username, System.currentTimeMillis());
            }
            
            // 更新在线统计
            int currentOnline = onlineCount.incrementAndGet();
            webSocketService.sendOnlineStatistics(currentOnline, executingCount.get());
            
            // 返回订阅确认消息
            Map<String, Object> response = new HashMap<>();
            response.put("type", "subscription_confirmed");
            response.put("sessionId", sessionId);
            response.put("username", username);
            response.put("timestamp", System.currentTimeMillis());
            response.put("message", "已连接到执行频道");
            
            return response;
        } catch (Exception e) {
            log.error("处理执行频道订阅失败", e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("type", "subscription_error");
            errorResponse.put("error", "订阅失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 处理客户端订阅系统状态
     */
    @SubscribeMapping("/topic/system")
    public Map<String, Object> subscribeSystem(Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "anonymous";
            log.info("用户 {} 订阅系统状态", username);
            
            Map<String, Object> response = new HashMap<>();
            response.put("type", "system_subscription_confirmed");
            response.put("username", username);
            response.put("timestamp", System.currentTimeMillis());
            response.put("onlineCount", onlineCount.get());
            response.put("executingCount", executingCount.get());
            response.put("message", "已连接到系统状态频道");
            
            return response;
        } catch (Exception e) {
            log.error("处理系统状态订阅失败", e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("type", "system_subscription_error");
            errorResponse.put("error", "订阅失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 处理客户端心跳消息
     */
    @MessageMapping("/heartbeat")
    @SendTo("/topic/heartbeat")
    public Map<String, Object> handleHeartbeat(@Payload Map<String, Object> heartbeat, Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "anonymous";
            String sessionId = (String) heartbeat.get("sessionId");
            
            log.debug("收到心跳: username={}, sessionId={}", username, sessionId);
            
            // 更新会话时间
            if (principal != null) {
                userSessions.put(username, System.currentTimeMillis());
            }
            
            Map<String, Object> response = new HashMap<>();
            response.put("type", "heartbeat_response");
            response.put("sessionId", sessionId);
            response.put("username", username);
            response.put("timestamp", System.currentTimeMillis());
            response.put("serverTime", System.currentTimeMillis());
            
            return response;
        } catch (Exception e) {
            log.error("处理心跳消息失败", e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("type", "heartbeat_error");
            errorResponse.put("error", "心跳处理失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 处理代码执行状态更新
     */
    @MessageMapping("/execution/status")
    public void handleExecutionStatus(@Payload Map<String, Object> status, Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "anonymous";
            String sessionId = (String) status.get("sessionId");
            String statusType = (String) status.get("status");
            
            log.debug("收到执行状态更新: username={}, sessionId={}, status={}", username, sessionId, statusType);
            
            // 更新执行统计
            if ("start".equals(statusType)) {
                int currentExecuting = executingCount.incrementAndGet();
                webSocketService.sendOnlineStatistics(onlineCount.get(), currentExecuting);
            } else if ("end".equals(statusType) || "error".equals(statusType)) {
                int currentExecuting = executingCount.decrementAndGet();
                webSocketService.sendOnlineStatistics(onlineCount.get(), Math.max(0, currentExecuting));
            }
            
        } catch (Exception e) {
            log.error("处理执行状态更新失败", e);
        }
    }

    /**
     * 处理用户连接事件
     */
    @MessageMapping("/user/connect")
    public void handleUserConnect(@Payload Map<String, Object> connectInfo, Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "anonymous";
            Long userId = connectInfo.get("userId") != null ? 
                Long.valueOf(connectInfo.get("userId").toString()) : null;
            
            log.info("用户连接: username={}, userId={}", username, userId);
            
            // 发送欢迎消息
            if (userId != null) {
                Map<String, Object> welcome = new HashMap<>();
                welcome.put("notificationType", "welcome");
                welcome.put("message", "欢迎使用在线代码执行平台！");
                welcome.put("username", username);
                
                webSocketService.sendUserNotification(userId, welcome);
            }
            
        } catch (Exception e) {
            log.error("处理用户连接失败", e);
        }
    }

    /**
     * 处理用户断开连接事件
     */
    @MessageMapping("/user/disconnect")
    public void handleUserDisconnect(@Payload Map<String, Object> disconnectInfo, Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "anonymous";
            String sessionId = (String) disconnectInfo.get("sessionId");
            
            log.info("用户断开连接: username={}, sessionId={}", username, sessionId);
            
            // 清理会话信息
            if (sessionId != null) {
                sessionUsers.remove(sessionId);
            }
            if (username != null && !"anonymous".equals(username)) {
                userSessions.remove(username);
            }
            
            // 更新在线统计
            int currentOnline = onlineCount.decrementAndGet();
            webSocketService.sendOnlineStatistics(Math.max(0, currentOnline), executingCount.get());
            
        } catch (Exception e) {
            log.error("处理用户断开连接失败", e);
        }
    }

    /**
     * 广播系统消息
     */
    @MessageMapping("/system/broadcast")
    @SendTo("/topic/system")
    public Map<String, Object> broadcastSystemMessage(@Payload Map<String, Object> message, Principal principal) {
        try {
            String username = principal != null ? principal.getName() : "system";
            
            log.info("广播系统消息: from={}, type={}", username, message.get("messageType"));
            
            message.put("type", "system_broadcast");
            message.put("from", username);
            message.put("timestamp", System.currentTimeMillis());
            
            return message;
        } catch (Exception e) {
            log.error("广播系统消息失败", e);
            Map<String, Object> errorResponse = new HashMap<>();
            errorResponse.put("type", "broadcast_error");
            errorResponse.put("error", "广播失败: " + e.getMessage());
            return errorResponse;
        }
    }

    /**
     * 获取当前在线统计
     */
    public Map<String, Integer> getOnlineStatistics() {
        Map<String, Integer> stats = new HashMap<>();
        stats.put("onlineCount", onlineCount.get());
        stats.put("executingCount", executingCount.get());
        return stats;
    }

    /**
     * 清理过期会话
     */
    public void cleanupExpiredSessions() {
        try {
            long currentTime = System.currentTimeMillis();
            long expireTime = 30 * 60 * 1000; // 30分钟过期
            
            userSessions.entrySet().removeIf(entry -> 
                currentTime - entry.getValue() > expireTime);
            
            log.debug("清理过期会话完成，当前活跃会话数: {}", userSessions.size());
        } catch (Exception e) {
            log.error("清理过期会话失败", e);
        }
    }
}